baubs git
src/stores/usePatternStore.test.ts main (3e6a6688) Text, 6.11 KB
import { describe, it, expect, beforeEach } from "vitest";
import {
usePatternStore,
selectPatternCenter,
selectUploadedPatternCenter,
selectRotatedBounds,
selectRotationCenterShift,
} from "./usePatternStore";
import type { PesPatternData } from "../formats/import/pesImporter";
// Mock pattern data for testing
const createMockPesData = (
bounds = {
minX: -100,
maxX: 100,
minY: -50,
maxY: 50,
},
): PesPatternData => ({
stitches: [[0, 0, 0, 0]],
threads: [],
uniqueColors: [],
penData: new Uint8Array(),
penStitches: {
stitches: [],
colorBlocks: [],
bounds: { minX: 0, maxX: 0, minY: 0, maxY: 0 },
},
colorCount: 1,
stitchCount: 1,
bounds,
});
describe("usePatternStore selectors", () => {
beforeEach(() => {
// Reset store state before each test
const state = usePatternStore.getState();
state.setPattern(createMockPesData(), "test.pes");
state.resetPatternOffset();
state.resetRotation();
state.clearUploadedPattern();
});
describe("selectPatternCenter", () => {
it("should return null when no pattern is loaded", () => {
// Clear the pattern
usePatternStore.setState({ pesData: null });
const center = selectPatternCenter(usePatternStore.getState());
expect(center).toBeNull();
});
it("should calculate center correctly for symmetric bounds", () => {
const state = usePatternStore.getState();
const center = selectPatternCenter(state);
expect(center).not.toBeNull();
expect(center!.x).toBe(0); // (minX + maxX) / 2 = (-100 + 100) / 2 = 0
expect(center!.y).toBe(0); // (minY + maxY) / 2 = (-50 + 50) / 2 = 0
});
it("should calculate center correctly for asymmetric bounds", () => {
const pesData = createMockPesData({
minX: 0,
maxX: 200,
minY: 0,
maxY: 100,
});
usePatternStore.setState({ pesData });
const state = usePatternStore.getState();
const center = selectPatternCenter(state);
expect(center).not.toBeNull();
expect(center!.x).toBe(100); // (0 + 200) / 2
expect(center!.y).toBe(50); // (0 + 100) / 2
});
});
describe("selectUploadedPatternCenter", () => {
it("should return null when no uploaded pattern", () => {
const state = usePatternStore.getState();
const center = selectUploadedPatternCenter(state);
expect(center).toBeNull();
});
it("should calculate center of uploaded pattern", () => {
const uploadedData = createMockPesData({
minX: 50,
maxX: 150,
minY: 25,
maxY: 75,
});
usePatternStore
.getState()
.setUploadedPattern(uploadedData, { x: 0, y: 0 });
const state = usePatternStore.getState();
const center = selectUploadedPatternCenter(state);
expect(center).not.toBeNull();
expect(center!.x).toBe(100); // (50 + 150) / 2
expect(center!.y).toBe(50); // (25 + 75) / 2
});
});
describe("selectRotatedBounds", () => {
it("should return original bounds when no rotation", () => {
const state = usePatternStore.getState();
const result = selectRotatedBounds(state);
expect(result).not.toBeNull();
expect(result!.bounds).toEqual({
minX: -100,
maxX: 100,
minY: -50,
maxY: 50,
});
expect(result!.center).toEqual({ x: 0, y: 0 });
});
it("should return null when no pattern", () => {
usePatternStore.setState({ pesData: null });
const state = usePatternStore.getState();
const result = selectRotatedBounds(state);
expect(result).toBeNull();
});
it("should calculate rotated bounds for 90 degree rotation", () => {
usePatternStore.getState().setPatternRotation(90);
const state = usePatternStore.getState();
const result = selectRotatedBounds(state);
expect(result).not.toBeNull();
// After 90° rotation, X and Y bounds should swap
expect(result!.bounds.minX).toBeCloseTo(-50, 0);
expect(result!.bounds.maxX).toBeCloseTo(50, 0);
expect(result!.bounds.minY).toBeCloseTo(-100, 0);
expect(result!.bounds.maxY).toBeCloseTo(100, 0);
});
it("should expand bounds for 45 degree rotation", () => {
usePatternStore.getState().setPatternRotation(45);
const state = usePatternStore.getState();
const result = selectRotatedBounds(state);
expect(result).not.toBeNull();
// After 45° rotation, bounds should expand
expect(Math.abs(result!.bounds.minX)).toBeGreaterThan(100);
expect(Math.abs(result!.bounds.minY)).toBeGreaterThan(50);
});
});
describe("selectRotationCenterShift", () => {
it("should return zero shift when no rotation", () => {
const state = usePatternStore.getState();
const rotatedBounds = state.pesData!.bounds;
const shift = selectRotationCenterShift(state, rotatedBounds);
expect(shift).toEqual({ x: 0, y: 0 });
});
it("should return null when no pattern", () => {
usePatternStore.setState({ pesData: null });
const state = usePatternStore.getState();
const shift = selectRotationCenterShift(state, {
minX: 0,
maxX: 100,
minY: 0,
maxY: 100,
});
expect(shift).toBeNull();
});
it("should calculate center shift for asymmetric pattern", () => {
const pesData = createMockPesData({
minX: 0,
maxX: 200,
minY: 0,
maxY: 100,
});
usePatternStore.setState({ pesData });
usePatternStore.getState().setPatternRotation(90);
const state = usePatternStore.getState();
const rotatedBounds = selectRotatedBounds(state)!.bounds;
const shift = selectRotationCenterShift(state, rotatedBounds);
expect(shift).not.toBeNull();
// Original center: (100, 50)
// After 90° rotation around center, new center should be slightly different
// due to the asymmetric bounds
expect(shift!.x).toBeCloseTo(0, 0);
expect(shift!.y).toBeCloseTo(0, 0);
});
});
});
Served by rngit 1.3.3 - Generated in 0.03s